package com.ruicar.afs.cloud.workflow.greatwall.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.service.ServiceInfo;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.data.lock.anno.Lock;
import com.ruicar.afs.cloud.workflow.api.enums.FlowStatus;
import com.ruicar.afs.cloud.workflow.greatwall.component.GwtProcessComponent;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtRequest;
import com.ruicar.afs.cloud.workflow.greatwall.dto.exception.FlowExceptionDto;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowBizData;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowNoticeException;
import com.ruicar.afs.cloud.workflow.greatwall.feign.GwtWorkFLowFeign;
import com.ruicar.afs.cloud.workflow.greatwall.mapper.AfsGreatWallWorkflowNoticeExceptionMapper;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowBizDataService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowNoticeExceptionService;
import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@AllArgsConstructor
public class AfsGreatWallWorkflowNoticeExceptionServiceImpl extends ServiceImpl<AfsGreatWallWorkflowNoticeExceptionMapper, AfsGreatWallWorkflowNoticeException> implements AfsGreatWallWorkflowNoticeExceptionService, ApplicationListener<ApplicationReadyEvent> {
    private final GwtWorkFLowFeign gwtWorkFLowFeign;
    private final AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService;
    private final AfsGreatWallWorkflowNoticeExceptionMapper afsGreatWallWorkflowNoticeExceptionMapper;
    private static final ScheduledExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadScheduledExecutor();
    @Override
    @Lock(keyConstant = ":flowexception:resolver", keys = "#flowExceptionDto.id")
    @Transactional(rollbackFor = Exception.class)
    public Boolean resolverException(FlowExceptionDto flowExceptionDto,boolean auto) {
        AfsGreatWallWorkflowNoticeException afsGreatWallWorkflowNoticeException = this.getById(flowExceptionDto.getId());
        if (afsGreatWallWorkflowNoticeException != null) {
            long errorCount = this.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getFlowInstanceId, afsGreatWallWorkflowNoticeException.getFlowInstanceId()).lt(AfsGreatWallWorkflowNoticeException::getId, afsGreatWallWorkflowNoticeException.getId()).ne(AfsGreatWallWorkflowNoticeException::getId, afsGreatWallWorkflowNoticeException.getId()));
            if (errorCount > 0) {
                throw new AfsBaseException(CommonConstants.FAIL, "必须按照业务id异常顺序来点击解决异常");
            }
            boolean success = true;
            if(afsGreatWallWorkflowNoticeException.getNoticeType().equals("auto-auto")){
                if(auto&&!needAutoRunAgain(afsGreatWallWorkflowNoticeException.getNoticeInfo())){
                    return Boolean.TRUE;
                }
                try {
                    gwtWorkFLowFeign.resumeFlowInstance(afsGreatWallWorkflowNoticeException.getBizDataId(), afsGreatWallWorkflowNoticeException.getNoticeInfo());
                } catch (Exception e) {
                    success = false;
                }
            }else {
                GwtRequest gwtRequest = JSON.parseObject(afsGreatWallWorkflowNoticeException.getNoticeInfo(), GwtRequest.class);
                success = GwtProcessComponent.gwtObjProcessor(afsGreatWallWorkflowNoticeException.getNoticeType()).processError(gwtRequest);
            }
            if (success) {
                this.removeById(afsGreatWallWorkflowNoticeException.getId());
                long count = this.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getFlowInstanceId, afsGreatWallWorkflowNoticeException.getFlowInstanceId()).ne(AfsGreatWallWorkflowNoticeException::getId, afsGreatWallWorkflowNoticeException.getId()));
                if (count == 0) {
                    AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData = afsGreatWallWorkflowBizDataService.getBizDataObjServiceIdAndDataId(afsGreatWallWorkflowNoticeException.getFlowServiceId(), afsGreatWallWorkflowNoticeException.getBizDataId());
                    afsGreatWallWorkflowBizData.setFlowStatus(FlowStatus.RUNING);
                    afsGreatWallWorkflowBizDataService.updateById(afsGreatWallWorkflowBizData);
                }
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        } else {
            throw new AfsBaseException(CommonConstants.FAIL, "异常不存在或已经处理");
        }
    }

    private boolean needAutoRunAgain(String exceptionId){
        Long count  = afsGreatWallWorkflowNoticeExceptionMapper.countExceptionCount(exceptionId);
        if(count<=2){
            return Boolean.TRUE;
        }else {
            return Boolean.FALSE;
        }
    }
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        schedule();
    }

    private void schedule() {
        //每30s自动处理一次异常
        EXECUTOR_SERVICE.scheduleWithFixedDelay(() -> {
            try {
                List<AfsGreatWallWorkflowNoticeException> afsGreatWallWorkflowNoticeExceptions = this.list(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getNoticeType,"auto-auto").orderByAsc(AfsGreatWallWorkflowNoticeException::getId));
                for (AfsGreatWallWorkflowNoticeException afsGreatWallWorkflowNoticeException : afsGreatWallWorkflowNoticeExceptions) {
                    long count = this.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getFlowInstanceId, afsGreatWallWorkflowNoticeException.getFlowInstanceId()).ne(AfsGreatWallWorkflowNoticeException::getId, afsGreatWallWorkflowNoticeException.getId()));
                    if(count==0){
                        log.info("自动处理流程异常{}-{}",afsGreatWallWorkflowNoticeException.getBizDataId(),afsGreatWallWorkflowNoticeException.getFlowInstanceId());
                        FlowExceptionDto flowExceptionDto = new FlowExceptionDto();
                        flowExceptionDto.setId(afsGreatWallWorkflowNoticeException.getId());
                        SpringContextHolder.getBean(AfsGreatWallWorkflowNoticeExceptionService.class).resolverException(flowExceptionDto,true);
                        ThreadUtil.sleep(100);
                    }
                }
            }catch (Throwable e){}
        }, 2, 30, TimeUnit.SECONDS);

    }
}
